//
//  LineChartView.swift
//  Speek
//
//  Created by ZhenyanShan on 2023/7/5.
//

import SwiftUI
import CoreData

struct LineChartView: View {
    @State var data: [AmountData] = []
    @State var selectedAmount: AmountData?
    @State private var isShowingAmount = false
    @State private var showAmountForIndex: Int? = nil
    @State private var scrollOffset: CGSize? =  .zero
    @State private var isScrolling: Bool = false
    @State private var currentPosition: CGFloat = 0
    @Binding var year : String
    @Binding var month : String
    @Binding var tag: Bool
    
    init(year: Binding<String>, month: Binding<String>, tag: Binding<Bool>) {
        self._year = year
        self._month = month
        self._tag = tag
        self._data = State(initialValue: getAmountDatas(year: year.wrappedValue, month: month.wrappedValue, tag: tag.wrappedValue))
    }


    var body: some View{
       
        VStack{
            GeometryReader { geometry in
                let line = createLine(in: geometry)
                let maxAmount = data.map { $0.amount }.max() ?? 0
                
                //左侧金额数字
                ForEach(0...5, id: \.self) { index in
                    let referenceValue = getReferenceValue(maxAmount: maxAmount, index: index)
                    let y = getYCoordinate(for: AmountData(year: "", month: "", amount: referenceValue), maxAmount: maxAmount, in: geometry)
                    
                    Text(String(format: "%.2f", referenceValue))
                        .font(.caption)
                        .foregroundColor(.gray)
                        .offset(x: -40, y: y + 43) // 向右移动文字标签的 x 坐标为 10
                }

                
                ScrollView(.horizontal){
                    ZStack{
                        
                        //参考线段
                        ForEach(0...5, id: \.self) { index in
                            let referenceValue = getReferenceValue(maxAmount: maxAmount, index: index)
                            let y = getYCoordinate(for: AmountData(year: "", month: "", amount: referenceValue), maxAmount: maxAmount, in: geometry)
                            
                            Path { path in
                                path.move(to: CGPoint(x: 20, y: y)) // 移动起点的 x 坐标为 40
                                path.addLine(to: CGPoint(x: geometry.size.width + 300, y: y))
                            }
                            .stroke(Color.gray.opacity(0.5), style: StrokeStyle(lineWidth: 1, dash: [5]))
                        }
                        
                        // 折线
                        line
                            .stroke(Color.blue, style: StrokeStyle(lineWidth: 2, lineCap: .round, lineJoin: .round))
                            .background(
                                GeometryReader { geo in
                                    Rectangle()
                                        .fill(Color.clear)
                                        .onTapGesture {
                                            let monthWidth = geo.size.width / CGFloat(data.count - 1)
                                            let monthIndex = Int((geo.frame(in: .global).midX) / monthWidth)
                                            selectedAmount = data[monthIndex]
                                        }
                                }
                            ).offset(x:30)
                        
                        
                        ForEach(data.indices) { index in
                            let expense = data[index]
                            let isSelected = expense == selectedAmount
                            
                            //点
                            Circle()
                                .fill(Color.purple)
                                .frame(width: 8, height: 8)
                                .position(x: getXCoordinate(for: expense, in: geometry), y: getYCoordinate(for: expense, maxAmount: maxAmount, in: geometry))
                                .offset(x: 30)
                                .onTapGesture {
                                    showAmountForIndex = isSelected ? nil : index
                                    selectedAmount = isSelected ? nil : expense
                                }
                            //点击后展示该月金额的方框
                                .overlay(
                                    VStack {
                                        if showAmountForIndex == index {
                                            Text(String(expense.amount))
                                                .font(.caption)
                                                .foregroundColor(.white)
                                                .padding(.vertical, 4)
                                                .padding(.horizontal, 1)
                                                .frame(width:50)
                                                .background(Color(hex: 0x3565FC))
                                                .clipShape(RoundedRectangle(cornerRadius: 4))
                                                .offset(x:30,y: -20)
                                        }
                                    }
                                        .position(x: getXCoordinate(for: expense, in: geometry), y: getYCoordinate(for: expense, maxAmount: maxAmount, in: geometry))
                                        .animation(.easeInOut)
                                )
                            
                            //下方月份标签
                            VStack {
                                Text(expense.month + "月")
                                    .font(.caption)
                                    .foregroundColor(.white)
                                    .padding(.vertical, 4)
                                    .padding(.horizontal, 1)
                                    .frame(width:40)
                                    .background(Color(hex: 0x8676FF))
                                    .clipShape(RoundedRectangle(cornerRadius: 4))
                                    .offset(x: 30,y: -20)
                            }.position(x: getXCoordinate(for: expense, in: geometry), y: geometry.size.height + 10)
                            
                                .onTapGesture {
                                    showAmountForIndex = isSelected ? nil : index
                                    selectedAmount = isSelected ? nil : expense
                                }
                            //点击后展示该月金额的方框
                                .overlay(
                                    VStack {
                                        if showAmountForIndex == index {
                                            Text(String(expense.amount))
                                                .font(.caption)
                                                .foregroundColor(.white)
                                                .padding(.vertical, 4)
                                                .padding(.horizontal, 1)
                                                .frame(width:50)
                                                .background(Color(hex: 0x3565FC))
                                                .clipShape(RoundedRectangle(cornerRadius: 4))
                                                .offset(x:30,y: -20)
                                        }
                                    }
                                        .position(x: getXCoordinate(for: expense, in: geometry), y: getYCoordinate(for: expense, maxAmount: maxAmount, in: geometry))
                                        .animation(.easeInOut)
                                )
                        }.frame(width:geometry.size.width + 300)
                        
                    }.offset(x:-10,y:50)
                    
                }
                .frame(height: 400)
            }.onAppear{
                data = getAmountDatas(year: year, month: month, tag: tag)
            }
            .onChange(of: year, perform: { _ in
                data = getAmountDatas(year: year, month: month, tag: tag)
            })
            .onChange(of: month, perform: { _ in
                data = getAmountDatas(year: year, month: month, tag: tag)
            })
            .onChange(of: tag, perform: { _ in
                data = getAmountDatas(year: year, month: month, tag: tag)
            })
        }

    }
    
    
    private func createLine(in geometry: GeometryProxy) -> Path {
        var path = Path()
        let maxAmount = data.map { $0.amount }.max() ?? 0
        
        path.move(to: CGPoint(x: 0, y: getYCoordinate(for: data[0], maxAmount: maxAmount, in: geometry)))
        
        for expense in data {
            let x = getXCoordinate(for: expense, in: geometry)
            let y = getYCoordinate(for: expense, maxAmount: maxAmount, in: geometry)
            path.addLine(to: CGPoint(x: x, y: y))
        }
        
        return path
    }
    
    
    private func getXCoordinate(for expense: AmountData, in geometry: GeometryProxy) -> CGFloat {
        let monthWidth = geometry.size.width / CGFloat(data.count - 1)*1.8
        let index = data.firstIndex { $0.id == expense.id } ?? 0
        return monthWidth * CGFloat(index)
    }

    private func getYCoordinate(for expense: AmountData, maxAmount: Double, in geometry: GeometryProxy) -> CGFloat {
        let maxHeight = geometry.size.height - 40
        var height = 0.0
        if CGFloat(maxAmount) == 0{
            height = (CGFloat(expense.amount) / CGFloat(100)) * CGFloat (maxHeight)
        }else{
            height = (CGFloat(expense.amount) / CGFloat(maxAmount)) * CGFloat (maxHeight)
        }
        return maxHeight - height
    }
    
    //获取折线图每个月的对应金额
    private func getAmountDatas(year: String, month:String, tag: Bool)->[AmountData]{
        var amountDatas: [AmountData] = []
        for index in 0...11{
            let amount = getTotalAmount(forYear: Int(year) ?? 0 , month: index + 1, tag: tag)
            let amountData = AmountData(year: year, month: String(index + 1), amount: amount )
            amountDatas.append(amountData)
        }
        return amountDatas
    }
    
    
    //获取ReferenceValue
    private func getReferenceValue(maxAmount:Double,index:Int)->Double{
        var referenceValue = 0.0
        if(maxAmount == 0){
            referenceValue = 100 * (1 - CGFloat(index) * 0.2)
        }else{
            referenceValue = maxAmount * (1 - CGFloat(index) * 0.2)
        }
        return referenceValue
    }
    

}



